package com.bj;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.casino.tool.CSM;
import com.casino.tool.P;

public class Game {

	private int runCount = 0;

	private int winCount = 0;

	private int lossCount = 0;

	private static double totalBet = 0;

	private static int realCountP = 0;

	private static int runTimes = 10000 * 10000;

	private static int rb = 0;

	public void start() {

		int stepBet = 5;

		double wb1 = 0;

		for (rb = 0; rb < 2; rb++) {
			realCountP = 0;
			CSM csm = new CSM(6, 13);
			int playerNum = 6;

			Player player[] = new Player[playerNum];

			for (int i = 0; i < playerNum; i++) {
				player[i] = new Player();
			}

			for (int i = 0; i < runTimes; i++) {

				P dealerP = csm.dealRandomCard();
				List<P> dealerPList = new ArrayList<P>();
				dealerPList.add(dealerP);
				double beginRCount = csm.getHiLoCount();
				for (int gg = 0; gg < playerNum; gg++) {
					List<Round> roundList = new ArrayList<Round>();
					Round round = new Round();

					if (rb == 0) {
						if (beginRCount >= 1) {
							realCountP++;
							round.setBetMoney(beginRCount+2);
						} else {
							round.setBetMoney(0);
						}
					} else {
						if (beginRCount >= 1) {
							realCountP++;
							round.setBetMoney(1);
						} else {
							round.setBetMoney(0);
						}
					}

					round.setPlayer(player[gg]);
					round.addP(csm.dealRandomCard());
					round.addP(csm.dealRandomCard());
					roundList.add(round);
					player[gg].setRoundList(roundList);
				}

				for (int gg = 0; gg < playerNum; gg++) {
//					playerAction(player[gg].getRoundList().get(0), dealerP, csm, true, beginRCount);
					playerBasicAction(player[gg].getRoundList().get(0), dealerP, csm, beginRCount);
					dealBasicSplite(player[gg].getRoundList().get(0), csm, dealerP, player[gg].getRoundList(), player[gg].getRoundList().size() > 1, beginRCount);
					player[gg].getRoundList().get(0).getPlayer().setSpliteTimes(0);
				}

				while (Dealer.isHit(dealerPList)) {
					P p = csm.dealRandomCard();
					dealerPList.add(p);
				}
				// for(P sps :dealerPList){
				// sps.print();
				// System.out.print(" ");
				// }
				// System.out.println("");

				int dealerPoint = Strategy.count(dealerPList);
				for (Player p : player) {

					for (Round r : p.getRoundList()) {
						//
						// for(P sps :r.getpList()){
						// sps.print();
						// System.out.print(" ");
						// }
						if (r.isDoubleBet()) {
							totalBet = totalBet + r.getBetMoney();
						}
						// System.out.println(r.isDoubleBet());
						runCount++;
						int rPoint = -1;
						if (r.isSurrender()) {
							halfCount++;
							r.getPlayer().adjustMoney(r.getBetMoney() * -0.5);
						} else if (r.isBust()) {
							lossCount++;
							r.getPlayer().adjustMoney(r.getBetMoney() * -1);
						} else if (Rule.isBlackJack(r.getpList()) && !r.isHasSplite()) {
							if (!Rule.isBlackJack(dealerPList)) {
								bjCount++;
								r.getPlayer().adjustMoney(r.getBetMoney() * 1.5);
							}
						} else if (Rule.isBlackJack(dealerPList)) {
							lossCount++;
							r.getPlayer().adjustMoney(r.getBetMoney() * -1);
							break;
						} else if (dealerPoint > 21) {
							if (r.isDoubleBet()) {

								dwin++;
								r.getPlayer().adjustMoney(r.getBetMoney() * 2);
							} else {
								winCount++;
								r.getPlayer().adjustMoney(r.getBetMoney() * 1);
							}

						} else {
							rPoint = Strategy.count(r.getpList());
							if (dealerPoint > rPoint) {

								if (r.isDoubleBet()) {
									dloss++;
									r.getPlayer().adjustMoney(r.getBetMoney() * -1 * 2);
								} else {
									lossCount++;
									r.getPlayer().adjustMoney(r.getBetMoney() * -1);
								}

							} else if (dealerPoint < rPoint) {

								if (r.isDoubleBet()) {
									dwin++;
									r.getPlayer().adjustMoney(r.getBetMoney() * 2);
								} else {
									winCount++;
									r.getPlayer().adjustMoney(r.getBetMoney());
								}
							} else {
								withdraw++;
							}
						}

					}

				}
				csm.returnCardsToMachine();
				// System.out.println("-------------");
			}
			// System.out.println(runCount);

			double mon = 0;

			for (int i = 0; i < playerNum; i++) {
				mon = mon + player[i].getMoney();
			}
			System.out.println(mon);

			// System.out.println((winCount - lossCount) + (dwin - dloss) * 2 -
			// halfCount * 0.5 + bjCount * 1.5);

			// System.out.println(hitsCount);
			// System.out.println(holdCount);
			// System.out.println(bustCount);
			//
			// System.out.println(withdraw);
			System.out.println(new BigDecimal(totalBet));
			System.out.println(mon * 100 / totalBet);
			System.out.println(realCountP * 1.0 / runTimes / playerNum);
			wb1 = wb1 + mon;
		}
		System.out.println(wb1 * 100 / totalBet);
	}

	public static int halfCount = 0;
	public static int withdraw = 0;
	public static int bjCount = 0;
	public static int dwin = 0;
	public static int dloss = 0;

	private void dealBasicSplite(Round round, CSM csm, P dealerP, List<Round> roundList, boolean hasNight, double rcount) {
		if (round.isSplite()) {

			Round roundSplite = new Round();
			roundSplite.setHasSplite(true);
			roundSplite.setPlayer(round.getPlayer());
			roundSplite.addP(round.getpList().remove(0));
			roundSplite.addP(csm.dealRandomCard());
//			 roundSplite.setBetMoney(round.getBetMoney());
			boolean call = Strategy.getNightCall(dealerP, round.getpList());
			if (rb == 0) {
				if (call) {
					roundSplite.setBetMoney(round.getBetMoney());
				} else {
					roundSplite.setBetMoney(round.getBetMoney());
				}
			} else {
				if (call) {
					roundSplite.setBetMoney(round.getBetMoney());
				} else {
					roundSplite.setBetMoney(0);
				}
			}

			round.setSplite(false);
			round.setHasSplite(true);
			round.addP(csm.dealRandomCard());
			roundList.add(roundSplite);
			playerBasicAction(round, dealerP, csm, rcount);

			if (round.isSplite()) {
				dealBasicSplite(round, csm, dealerP, roundList, hasNight, rcount);
			}

			playerBasicAction(roundSplite, dealerP, csm, rcount);

			if (roundSplite.isSplite()) {
				dealBasicSplite(round, csm, dealerP, roundList, hasNight, rcount);
			}
		}
	}

	private void playerAction(Round round, P dealerP, CSM csm, boolean hasNight, double rcount) {
		int s;
		while (true) {
			s = Strategy.getNightStrategy(dealerP, rcount, round.getPlayer().getSpliteTimes(), round, round.getPlayer().getRoundList().size() >= 4);
			if (s == Strategy.HIT) {
				hitsCount++;
				round.addP(csm.dealRandomCard());
			} else if (s == Strategy.SURRENDER) {
				round.setSurrender(true);
				break;
			} else if (s == Strategy.DOUBLEBET) {
				round.setDoubleBet(true);
				round.addP(csm.dealRandomCard());
				break;
			} else if (s == Strategy.BUST) {
				bustCount++;
				round.setBust(true);
				break;
			} else if (s == Strategy.HOLD) {
				holdCount++;
				break;
			} else if (s == Strategy.SPLITE) {
				round.getPlayer().addSpliteTimes();
				round.setSplite(true);
				break;
			}
		}

	}

	private void playerBasicAction(Round round, P dealerP, CSM csm, double rcount) {
		int s;
		while (true) {
			s = Strategy.getBasicStrategy(dealerP, round.getpList(), round.isHasSplite(), round.getPlayer().getRoundList().size() >= 4, false, csm.getHiLoCount());
			if (s == Strategy.HIT) {
				hitsCount++;
				round.addP(csm.dealRandomCard());
			} else if (s == Strategy.SURRENDER) {
				round.setSurrender(true);
				break;
			} else if (s == Strategy.DOUBLEBET) {
				round.setDoubleBet(true);
				round.addP(csm.dealRandomCard());
				break;
			} else if (s == Strategy.BUST) {
				bustCount++;
				round.setBust(true);
				break;
			} else if (s == Strategy.HOLD) {
				holdCount++;
				break;
			} else if (s == Strategy.SPLITE) {
				round.getPlayer().addSpliteTimes();
				round.setSplite(true);
				break;
			}
		}

	}

	public static double sum = 0;

	public static double hitsCount = 0;
	public static double holdCount = 0;
	public static double bustCount = 0;

	public static void main(String args[]) {
		Game g = new Game();
		g.start();
	}

	public class Round {
		private Player player;
		private List<P> pList = new ArrayList<P>();
		private double betMoney;
		private boolean surrender;
		private boolean doubleBet;
		private boolean bust;
		private boolean splite;
		private boolean hasSplite;

		public boolean isHasSplite() {
			return hasSplite;
		}

		public void setHasSplite(boolean hasSplite) {
			this.hasSplite = hasSplite;
		}

		public boolean isSplite() {
			return splite;
		}

		public void setSplite(boolean splite) {
			this.splite = splite;
		}

		public boolean isBust() {
			return bust;
		}

		public void setBust(boolean bust) {
			this.bust = bust;
		}

		public boolean isSurrender() {
			return surrender;
		}

		public void setSurrender(boolean surrender) {
			this.surrender = surrender;
		}

		public boolean isDoubleBet() {

			return doubleBet;
		}

		public void setDoubleBet(boolean doubleBet) {

			this.doubleBet = doubleBet;
		}

		public void addP(P p) {
			pList.add(p);

		}

		public Player getPlayer() {
			return player;
		}

		public void setPlayer(Player player) {
			this.player = player;
		}

		public List<P> getpList() {
			return pList;
		}

		public void setpList(List<P> pList) {
			this.pList = pList;
		}

		public double getBetMoney() {
			return betMoney;
		}

		public void setBetMoney(double betMoney) {
			totalBet = totalBet + betMoney;
			this.betMoney = betMoney;
		}

	}

}
